package com.mugui.spring.net.session;

import java.io.Serializable;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Iterator;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantLock;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionContext;

import cn.hutool.cache.impl.TimedCache;
import cn.hutool.core.util.ArrayUtil;

public class SessionContext {
	@SuppressWarnings("serial")
	private static final TimedCache<String, TempSession> mymap = new TimedCache<String,TempSession>(60000 * 60 * 6){
		@Override
		protected void onRemove(String key, TempSession cachedObject) {
			cachedObject.clear();
		}
	};
	static {
		mymap.schedulePrune(60000*60);
	}
//	private static ConcurrentHashMap<String, TempSession> mymap = new ConcurrentHashMap<String, TempSession>();

	private static ThreadLocal<HttpSession> threadLocal=new ThreadLocal<>();
	
	public static synchronized void AddSession(HttpSession session) {
		if (session != null) {
			threadLocal.set(session);
			TempSession tempSession = mymap.get(session.getId());
			if (tempSession == null) {
				mymap.put(session.getId(), new TempSession(session));
			}else {
				tempSession.session=session;
			}
		}
	}
	public static HttpSession getLocalSession() {
		return threadLocal.get();
	}
	public static synchronized void DelSession(HttpSession session) {
		if (session != null) {
			try {
				threadLocal.remove();
				mymap.remove(session.getId());
			} catch (Exception e) {
			}
			session.invalidate();
		}
	}
	public static void DelLocalSession() {
		threadLocal.remove();
	}

	public static synchronized HttpSession getSession(String session_id) {
		if (session_id == null)
			return null;
		return mymap.get(session_id);
	}

	public static Iterator<TempSession> AllSession() {
		return mymap.iterator();
	}

//	private static Jedis redisClient = RedisAccess.getRedisClient(8);

	private static class TempSession implements HttpSession,Serializable {
		HttpSession session;
		private ConcurrentHashMap<String, Object> hashMap = new ConcurrentHashMap<String, Object>() {
			/**
			 * 
			 */
			private static final long serialVersionUID = 1L;

			@Override
			public void clear() {
				for (Object object : hashMap.values()) {
					if (object instanceof ReentrantLock) {
						ReentrantLock lock = (ReentrantLock) object;
						try {
							if (lock.isHeldByCurrentThread())
								lock.unlock();
						} catch (Exception e) {
						}
					}
				}
				super.clear();
			}
		};
		public void clear() {
			hashMap.clear();
		}
		public TempSession(HttpSession session) {
			this.session = session;
		}

		public Object getAttribute(String key) {
			Object object = hashMap.get(key);
			if (object == null) {
				return session.getAttribute(key);
			}
			return object;
		}

		@Override
		public String getId() {
			return session.getId();
		}

		@Override
		public void setAttribute(String attributeName, Object attributeValue) {
			hashMap.put(attributeName, attributeValue);
			session.setAttribute(attributeName, attributeValue);
		}

		@Override
		public void removeAttribute(String attributeName) {
			hashMap.remove(attributeName);
			session.removeAttribute(attributeName);
		}

		@Override
		public long getCreationTime() {
			return session.getCreationTime();
		}

		@Override
		public long getLastAccessedTime() {
			return session.getLastAccessedTime();
		}

		@Override
		public ServletContext getServletContext() {
			return session.getServletContext();
		}

		@Override
		public void setMaxInactiveInterval(int interval) {
			session.setMaxInactiveInterval(interval);
		}

		@Override
		public int getMaxInactiveInterval() {
			return session.getMaxInactiveInterval();
		}

		@Override
		public HttpSessionContext getSessionContext() {
			return session.getSessionContext();
		}

		@Override
		public Object getValue(String name) {
			Object object = hashMap.get(name);
			return object;
		}

		@Override
		public Enumeration<String> getAttributeNames() {
			return session.getAttributeNames();
		}

		@Override
		public String[] getValueNames() {
			return ArrayUtil.toArray(new HashSet<String>(hashMap.keySet()).iterator(), String.class);
		}

		@Override
		public void putValue(String name, Object value) {
			hashMap.put(name, value);
		}

		@Override
		public void removeValue(String name) {
			hashMap.remove(name);
		}

		@Override
		public void invalidate() {
			session.invalidate();
		}

		@Override
		public boolean isNew() {
			return session.isNew();
		}

	}


}
